package com.puzzlebazar.client.heyawake;

import com.puzzlebazar.client.main.control.GenericController;
import com.puzzlebazar.client.puzzle.control.PuzzleController;
import com.puzzlebazar.client.puzzle.model.History;
import com.puzzlebazar.client.puzzle.model.HistoryMove;
import com.puzzlebazar.client.puzzle.model.Move;
import com.puzzlebazar.client.puzzle.model.MoveTimer;
import com.puzzlebazar.client.puzzle.view.ExtPuzzleView;
import com.puzzlebazar.client.squaregrid.view.CellHighlighterBasic;
import com.puzzlebazar.client.squaregrid.view.ComponentHighlighter;

public class HeyawakeController extends PuzzleController {
	
	private final HeyawakeModel model;
	private final CreateRoomsState createRoomsState;
	private final EditRoomValueState editRoomValueState;
	private final PlayState playState;
	
	/**
	 * Creates a controller to edit an heyawake board
	 * @param model The associated heyawake model
	 * @param history The associated history
	 * @param moveTimer The move timer
	 * @param view The view for the heyawake
	 * @param parentController The parent of this subcontroller
	 * 
	 * @throws Exception
	 */
	public HeyawakeController( 
			HeyawakeModel model, 
			History history,
			MoveTimer moveTimer,
			ExtPuzzleView view,
			GenericController parentController ) throws Exception {
		super( model, history, moveTimer, view, parentController );

		this.model = model;
		createRoomsState = new CreateRoomsState( getModel(), getView(), this, history, moveTimer );
		editRoomValueState = new EditRoomValueState( getModel(), getView(), this, history, moveTimer );
		playState = new PlayState( getModel(), getView(), this, history, moveTimer );
	}

	@Override
	protected HeyawakeModel getModel() {
		return model;
	}
	
	/**
	 * Get the attached view as an HeyawakeView
	 * 
	 * @return The attached heyawake view
	 */
	private HeyawakeView getView() {
		return (HeyawakeView)view.getPuzzleView();
	}
	

	@Override
	public void startEditPuzzle() {
		super.startEditPuzzle();
		switchToCreateRooms();		
	}

	@Override
	public void startEditTutorial() {
		super.startEditTutorial();
		switchToCreateRooms();		
	}

	@Override
	public void startPlayPuzzle() {
		super.startPlayPuzzle();
		switchToPlay();		
	}
	
	/**
	 * Switch to the state for creating room
	 */
	public void switchToCreateRooms() {
		if( !leaveCurrentState() ) return;
		enterState( createRoomsState );
	}

	/**
	 * Switch to the state for editing room values
	 * 
	 * @param room Existing room into which to edit a value
	 */
	public void switchToEditRoomValue( Room room ) {
		// TODO Should throw an exception if room doesn't exist?
		if( !leaveCurrentState() ) return;
		editRoomValueState.setRoom( room );
		enterState( editRoomValueState );
	}

	/**
	 * Switch to the state for playing the puzzle
	 */
	public void switchToPlay() {
		if( !leaveCurrentState() ) return;
		enterState( playState );
	}
	
	protected void edit() {
		switchToCreateRooms();
	}

	@Override
	protected void play() {
		switchToPlay();
	}

	@Override
	protected void clear() {
		if( currentState == editRoomValueState )
			switchToCreateRooms();
			
		Move move;
		if( currentState == createRoomsState )
			move = getModel().clear( moveTimer.peekTime() );
		else
			move = getModel().clearStates( moveTimer.peekTime() );
		HistoryMove historyMove = history.clear( move );
		getModel().notifyObservers(move);
		history.notifyObservers(historyMove);
		moveTimer.step();
		moveTimer.notifyObservers();
	}
	
	@Override
	protected void verify() {
		isSolutionValid( getModel(), new ComponentHighlighter( null, null, 
				new CellHighlighterBasic( getView().getHighlightLayer(), "yellowfill transparent", "verification" ) ) );
	}

	@Override
	protected void prepareSavePlayHistory() {
	}

	@Override
	protected void prepareSaveTutorial() {
		if( currentState == editRoomValueState )
			switchToCreateRooms();
	}
	
	@Override
	protected void prepareSavePuzzle() {
		if( currentState == editRoomValueState )
			switchToCreateRooms();
	}

	@Override
	protected void prepareExit() {
	}

	@Override
	public void release() {
		super.release();
		createRoomsState.release();
		editRoomValueState.release();
		playState.release();
	}
	
}
